import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/animation.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class LoadingTextChangeWidget extends StatefulWidget {
  @override
  _LoadingTextChangeWidgetState createState() =>
      _LoadingTextChangeWidgetState();
}

class _LoadingTextChangeWidgetState extends State<LoadingTextChangeWidget>
    with SingleTickerProviderStateMixin {
  AnimationController? _controller;
  Animation<double>? _currentAnimation;

  late ValueNotifier<double> _animationListenable;

  int currentText = 50;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(duration: Duration(seconds: 1), vsync: this)
          ..repeat();
    _initAnimation();
  }

  void _initAnimation() {
    CurveTween curveTween = CurveTween(curve: Curves.easeInOut);
    _currentAnimation = TweenSequence<double>([
      TweenSequenceItem<double>(
          tween: Tween(begin: 0.0, end: 1.0).chain(curveTween), weight: 1),
    ]).animate(_controller!);

    _animationListenable = ValueNotifier<double>(_currentAnimation?.value ?? 0);

    _controller?.addListener(() {
      _animationListenable.value = _currentAnimation?.value ?? 0;
      setState(() {});
    });
    _controller?.forward();
    _currentAnimation?.addStatusListener((status) {
      print("动画status进度${_controller?.status}");
      if (_controller!.status == AnimationStatus.completed) {
        currentText = currentText + 1;
        _controller?.reset();
        _controller?.forward();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Container(
            color: Color(0xFFFFAC00),
            alignment: Alignment.center,
            height: 20,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                currentText >= 60
                    ? CustomPaint(
                        painter: _TextChangePainter(
                          currentText: (currentText / 60).toInt(),
                          factor: _animationListenable,
                        ),
                      )
                    : Text("00"),
                Text(":"),
                CustomPaint(
                  painter: _TextChangePainter(
                    currentText: currentText % 60,
                    factor: _animationListenable,
                  ),
                ),
              ],
            )),
      ),
    );
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }
}

class _TextChangePainter extends CustomPainter {
  int currentText = 1;

  final ValueNotifier<double>? factor;

  _TextChangePainter({required this.currentText, this.factor});

  @override
  void paint(Canvas canvas, Size size) {
    Paint _painter = Paint()
      ..color = Color(0xFFE70D0D)
      ..style = PaintingStyle.fill
      ..isAntiAlias = true;

    double animator = factor?.value ?? 0;
    print("文本进度${factor?.value}");
    canvas.drawRect(Rect.fromLTRB(0, 0, 100, 30), _painter);

    if (currentText != 0 && currentText % 10 == 0) {
      int textSecond = 0;
      int lastText = 9;
      //秒这一部分
      createSecond(textSecond, lastText, animator, canvas);

      //分钟这一部分
      int minuteText = (currentText / 10).toInt();
      var textMinutePainter = TextPainter(
        text: TextSpan(
            text: "${minuteText}",
            style: TextStyle(color: Color(0xFF003EF5), fontSize: 24)),
        textDirection: TextDirection.ltr,
        textWidthBasis: TextWidthBasis.longestLine,
        maxLines: 1,
      )
        // 可以传入minWidth，maxWidth来限制它的宽度，如不传，文字会绘制在一行
        ..layout();

      //上面的文字
      var currentTextDisPlayHeight =
          (textMinutePainter.height * (1 - animator));
      textMinutePainter.paint(canvas, Offset(-20, currentTextDisPlayHeight));

      var textMinuteLastPainter = TextPainter(
        text: TextSpan(
            text: "${minuteText - 1}",
            style: TextStyle(color: Color(0xFF003EF5), fontSize: 24)),
        textDirection: TextDirection.ltr,
        textWidthBasis: TextWidthBasis.longestLine,
        maxLines: 1,
      )..layout();
      textMinuteLastPainter.paint(
          canvas, Offset(-20, -textMinuteLastPainter.height * animator));


    } else {
      //绘制秒的切换效果
      int textSecond = currentText % 10 == 0 ? 1 : currentText % 10;
      int lastText = textSecond - 1;
      createSecond(textSecond, lastText, animator, canvas);

      //绘制固定的分钟的效果
      var textMPainter = TextPainter(
        text: TextSpan(
            text: "${(currentText / 10).toInt()}",
            style: TextStyle(color: Color(0xFF003EF5), fontSize: 24)),
        textDirection: TextDirection.ltr,
        textWidthBasis: TextWidthBasis.longestLine,
        maxLines: 1,
      )
        // 可以传入minWidth，maxWidth来限制它的宽度，如不传，文字会绘制在一行
        ..layout();
      textMPainter.paint(canvas, Offset(-20, 0));
    }
  }

  void createSecond(
      int currentText, int lastText, double animator, ui.Canvas canvas) {
    //上部分
    var textSecondPainter = TextPainter(
      text: TextSpan(
          text: "${currentText}",
          style: TextStyle(color: Color(0xFF003EF5), fontSize: 24)),
      textDirection: TextDirection.ltr,
      textWidthBasis: TextWidthBasis.longestLine,
      maxLines: 1,
    )
      // 可以传入minWidth，maxWidth来限制它的宽度，如不传，文字会绘制在一行
      ..layout();

    //上部分文字
    var currentTextDisPlayHeight = (textSecondPainter.height * (1 - animator));
    textSecondPainter.paint(canvas, Offset(0, currentTextDisPlayHeight));

    var textSecondLastPainter = TextPainter(
      text: TextSpan(
          text: "${lastText}",
          style: TextStyle(color: Color(0xFF003EF5), fontSize: 24)),
      textDirection: TextDirection.ltr,
      textWidthBasis: TextWidthBasis.longestLine,
      maxLines: 1,
    )
      // 可以传入minWidth，maxWidth来限制它的宽度，如不传，文字会绘制在一行
      ..layout();

    //下部分文字
    textSecondLastPainter.paint(
        canvas, Offset(0, -textSecondLastPainter.height * animator));


    //遮罩层，可以去掉 看看效果
    Paint _painter = Paint()
      ..color = Color(0xFFB7FF00)
      ..style = PaintingStyle.fill
      ..isAntiAlias = true;
    canvas.drawRect(Rect.fromLTRB(0, -textSecondLastPainter.height, 100, 0), _painter);
    canvas.drawRect(Rect.fromLTRB(0, textSecondLastPainter.height, 100, textSecondLastPainter.height+30), _painter);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  static Size boundingTextSize(String text, TextStyle style,
      {int maxLines = 2 ^ 31, double maxWidth = double.infinity}) {
    if (text == null || text.isEmpty) {
      return Size.zero;
    }
    final TextPainter textPainter = TextPainter(
        textDirection: TextDirection.ltr,
        text: TextSpan(text: text, style: style),
        maxLines: maxLines)
      ..layout(maxWidth: maxWidth);
    return textPainter.size;
  }

  void _paragraphCanvas(ui.Canvas canvas, ui.Paint _painter) {
    final paragraphStyle = ui.ParagraphStyle(
        // 字体方向，有些国家语言是从右往左排版的
        textDirection: TextDirection.ltr,
        // 字体对齐方式
        textAlign: TextAlign.justify,
        fontSize: 24,
        maxLines: 1,
        // 字体超出大小时显示的提示
        ellipsis: '...',
        fontWeight: FontWeight.bold,
        fontStyle: FontStyle.italic,
        height: 1,
        // 当我们设置[TextStyle.height]时 这个高度是否应用到字体顶部和底部
        textHeightBehavior: TextHeightBehavior(
            applyHeightToFirstAscent: true, applyHeightToLastDescent: true));
    // 第二步，根据ParagraphStyle生成ParagraphBuilder,第三步，添加文字。ParagraphBuilder类有个addText方法专门用于接收文字
    final paragraphBuilder = ui.ParagraphBuilder(paragraphStyle)..addText('1');
    // 第四步，通过build取到Paragraph类
    var paragraph = paragraphBuilder.build();

    // 第五步，根据宽高进行布局(layout)
    paragraph.layout(ui.ParagraphConstraints(
      width: 100,
    ));
    // 画一个辅助矩形（可以通过paragraph.width和paragraph.height来获取绘制文字的宽高）
    canvas.drawRect(
        Rect.fromLTRB(0, 0, paragraph.width, paragraph.height), _painter);
    // 第六步绘制(paint)
    canvas.drawParagraph(paragraph, Offset(0, 0));
  }
}
